package timer

import (
	"encoding/json"
	"fabric-explorer/tools"
	"fmt"
	"math/rand"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
)

const (
	PRODUCER  = "auto_producer"
	BUYER     = "auto_buyer"
	CHAINOCDE = "asset_transfer"
)

type Asset struct {
	Id       string `json:"Id"`
	Name     string `json:"Name"`
	Owner    string `json:"Owner"`
	MetaData string `json:"MetaData"`
	Value    int    `json:"Value"`
}

var interval int
var start bool

func init() {
	interval = 100
	start = true
}

//改间隔
func AutoChangeInterval(c *gin.Context) {
	s := c.Query("interval")
	i, err := strconv.Atoi(s)
	if err != nil {
		tools.FailResult(c, "interval参数错误")
		return
	}
	interval = i
	tools.SuccessResult(c, interval)
}

//改间隔
func AutoChangeStart(c *gin.Context) {
	s := c.Query("start")
	if s == "true" {
		start = true
	} else if s == "false" {
		start = false
	}
	tools.SuccessResult(c, s)
}

//自动执行脚本
func AutoExec() {
	//1.新建用户，如果存在则跳过
	createUser()
	//2.随机一段时间给buyer一些money
	go func() {
		for {
			i := rand.Intn(interval)
			time.Sleep(time.Second * time.Duration(i))
			if start {
				obtainBalance()
			}
		}
	}()
	//2.随机一段时间给producer一些asset
	go func() {
		for {
			i := rand.Intn(interval)
			time.Sleep(time.Second * time.Duration(i))
			if start {
				enrollAsset()
			}
		}
	}()
	//3.随机一段时间给buyer买producer的资产
	go func() {
		for {
			i := rand.Intn(interval)
			time.Sleep(time.Second * time.Duration(i))
			if start {
				buyAsset()
			}
		}
	}()
}

//创建用户
func createUser() {
	_, err := tools.ExecuteChaincode(CHAINOCDE, "RegisterUser", PRODUCER, PRODUCER)
	if err != nil {
		fmt.Printf("auto_chaincode[%v],auto_producer用户已存在,错误信息:%s\n", CHAINOCDE, err)
	}
	_, err = tools.ExecuteChaincode(CHAINOCDE, "RegisterUser", BUYER, BUYER)
	if err != nil {
		fmt.Printf("auto_chaincode[%v],auto_buyer用户已存在,错误信息:%s\n", CHAINOCDE, err)
	}
}

//获得余额
func obtainBalance() {
	money := rand.Intn(100)
	_, err := tools.ExecuteChaincode(CHAINOCDE, "ObtainBalance", BUYER, strconv.Itoa(money))
	if err != nil {
		fmt.Printf("auto_chaincode[%v],obtainBalance失败,错误信息:%s\n", CHAINOCDE, err)
		return
	}
	fmt.Printf("auto_chaincode[%v],obtainBalance成功,money:%v\n", CHAINOCDE, money)
	//查询当前总余额
	getBalance()
}

//查询余额
func getBalance() int {
	result, err := tools.QueryChaincode(CHAINOCDE, "BalanceOf", BUYER)
	if err != nil {
		fmt.Printf("auto_chaincode[%v],QueryChaincode失败,错误信息:%s\n", CHAINOCDE, err)
		return 0
	}
	s := string(result)
	x, err := strconv.Atoi(s)
	if err != nil {
		fmt.Printf("auto_chaincode[%v],QueryChaincode失败,错误信息:%s\n", CHAINOCDE, err)
		return 0
	}
	fmt.Printf("auto_chaincode[%v],buyer目前的总余额有:%v\n", CHAINOCDE, x)
	return int(x)
}

//登记新的资产
func enrollAsset() {
	assetId := "auto_asset_" + strconv.Itoa(int(time.Now().UnixMilli()))
	assetName := assetId
	asssetValue := strconv.Itoa(rand.Intn(100))
	result, err := tools.ExecuteChaincode(CHAINOCDE, "AssetEnroll", assetId, assetName, PRODUCER, "", asssetValue)
	if err != nil {
		fmt.Printf("auto_chaincode[%v],enrollAsset失败,错误信息:%s\n", CHAINOCDE, err)
		return
	}
	fmt.Printf("auto_chaincode[%v],资产登记成功:%s\n", CHAINOCDE, result)
}

//购买资产
func buyAsset() {
	//查询producer的所有资产
	assets := queryAllAssets()
	if assets == nil {
		fmt.Printf("auto_chaincode[%v],buyAsset,错误信息:%s\n", CHAINOCDE, "asset query fail")
		return
	}
	//查询buyer的余额
	balance := getBalance()
	//找一个买的起的asset
	assetId := ""
	for _, asset := range assets {
		if asset.Value <= balance {
			assetId = asset.Id
			break
		}
	}
	if assetId == "" {
		fmt.Printf("auto_chaincode[%v],buyAsset,错误信息:%s\n", CHAINOCDE, "find available asset fail")
		return
	}
	_, err := tools.ExecuteChaincode(CHAINOCDE, "AssetTransfer", assetId, PRODUCER, BUYER)
	if err != nil {
		fmt.Printf("auto_chaincode[%v],buyAsset失败,错误信息:%s\n", CHAINOCDE, err)
		return
	}
	fmt.Printf("auto_chaincode[%v],buyAsset成功,assetId:%s\n", CHAINOCDE, assetId)
}

//查询producer的所有资产
func queryAllAssets() []*Asset {
	result, err := tools.QueryChaincode(CHAINOCDE, "QueryUserAssets", PRODUCER)
	if err != nil {
		fmt.Printf("auto_chaincode[%v],queryAllAssets失败,错误信息:%s\n", CHAINOCDE, err)
		return nil
	}
	var assets []*Asset
	err = json.Unmarshal(result, &assets)
	if err != nil {
		fmt.Printf("auto_chaincode[%v]queryAllAssets失败,错误信息:%s\n", CHAINOCDE, err)
		return nil
	}
	fmt.Printf("auto_chaincode[%v]查询producer所有的资产:%v\n", CHAINOCDE, &assets)
	return assets
}
